#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include"data_struct.h"

int seqlist_init(seqlist_t **mylist, int size, int capacity){
	*mylist = malloc(sizeof(seqlist_t));
	if(*mylist == NULL)
		return -1;
	(*mylist)->arr = calloc(capacity, size);
	if((*mylist)->arr == NULL){
		free(*mylist);
		*mylist = NULL;
		return -1;
	}
	(*mylist)->nmemb = 0;
	(*mylist)->size = size;
	(*mylist)->capacity = capacity;

	return 0;

}

int seqlist_isfull(const seqlist_t *mylist){
	return mylist->nmemb == mylist->capacity;
}

int seqlist_empty(const seqlist_t *mylist){
	return !(mylist->nmemb);
}

int seqlist_insert(seqlist_t *mylist, const void *newdata){
	if(seqlist_isfull(mylist)){		
		return -1;
	}else{
		memcpy((char *)(mylist->arr) + mylist->nmemb * mylist->size, newdata, mylist->size);
		mylist->nmemb += 1;
	}
	return 0;	
}
static int __find(const seqlist_t *mylist, const void *key, int(*cmp)(const void *data, const void *key)){
	int i;
	for(i = 0; i < mylist->nmemb; i++){
		if(cmp((char *)(mylist->arr) + i * mylist->size, key) == 0){
			return i;
		}
	}
	return -1;
}
int seqlist_delete(seqlist_t *mylist, const void *key, int(*cmp)(const void *data, const void *key)){
	int f = __find(mylist, key, cmp);
	if(f != -1){
		memmove((char *)(mylist->arr) + f * mylist->size, (char *)(mylist->arr) + (f + 1) * mylist->size, (mylist->nmemb - (f + 1)) * mylist->size);
		memset((char *)(mylist->arr) + (mylist->nmemb - 1) * (mylist->size), 0, mylist->size);
		mylist->nmemb -= 1;
		return 0;
	}else{
		return -1;
	}
		
}

int seqlist_update(const seqlist_t *mylist, const void *key, int(*cmp)(const void *data, const void *key), const void *newdata){
	int f = __find(mylist, key, cmp);
	if(f != -1){
		memcpy((char *)(mylist->arr) + (f * mylist->size), newdata, mylist->size);
		return 0;
	}else{
		return -1;
	}
}

void *seqlist_search(const seqlist_t *mylist, const void *key, int(*cmp)(const void *data, const void *key)){
	int f = __find(mylist, key, cmp);
	if(f != -1){
		return (char *)(mylist->arr) + f * mylist->size;
	}else{
		return NULL;
	}

}

void seqlist_traval(const seqlist_t *mylist, void(*pri)(const void *)){
	int i;
	for(i = 0; i < mylist->nmemb; i++){
		pri((char *)(mylist->arr) + i * mylist->size);
	}

}

void seqlist_destroy(seqlist_t **mylist){
	if(*mylist){
		free((*mylist)->arr);
		(*mylist)->arr = NULL;
		free(*mylist);
		*mylist = NULL;
	}
}


